/*

 * jcapimin.c

 *

 * Copyright (C) 1994-1995, Thomas G. Lane.

 * This file is part of the Independent JPEG Group's software.

 * For conditions of distribution and use, see the accompanying README file.

 *

 * This file contains application interface code for the compression half

 * of the JPEG library.  These are the "minimum" API routines that may be

 * needed in either the normal full-compression case or the transcoding-only

 * case.

 *

 * Most of the routines intended to be called directly by an application

 * are in this file or in jcapistd.c.  But also see jcparam.c for

 * parameter-setup helper routines, jcomapi.c for routines shared by

 * compression and decompression, and jctrans.c for the transcoding case.

 */



#define JPEG_INTERNALS

#include "jinclude.h"

#include "jpeglib.h"





/*

 * Initialization of a JPEG compression object.

 * The error manager must already be set up (in case memory manager fails).

 */



GLOBAL void

jpeg_create_compress (j_compress_ptr cinfo)

{

  int i;



  /* For debugging purposes, zero the whole master structure.

   * But error manager pointer is already there, so save and restore it.

   */

  {

    struct jpeg_error_mgr * err = cinfo->err;

    MEMZERO(cinfo, SIZEOF(struct jpeg_compress_struct));

    cinfo->err = err;

  }

  cinfo->is_decompressor = FALSE;



  /* Initialize a memory manager instance for this object */

  jinit_memory_mgr((j_common_ptr) cinfo);



  /* Zero out pointers to permanent structures. */

  cinfo->progress = NULL;

  cinfo->dest = NULL;



  cinfo->comp_info = NULL;



  for (i = 0; i < NUM_QUANT_TBLS; i++)

    cinfo->quant_tbl_ptrs[i] = NULL;



  for (i = 0; i < NUM_HUFF_TBLS; i++) {

    cinfo->dc_huff_tbl_ptrs[i] = NULL;

    cinfo->ac_huff_tbl_ptrs[i] = NULL;

  }



  cinfo->input_gamma = 1.0;	/* in case application forgets */



  /* OK, I'm ready */

  cinfo->global_state = CSTATE_START;

}





/*

 * Destruction of a JPEG compression object

 */



GLOBAL void

jpeg_destroy_compress (j_compress_ptr cinfo)

{

  jpeg_destroy((j_common_ptr) cinfo); /* use common routine */

}





/*

 * Abort processing of a JPEG compression operation,

 * but don't destroy the object itself.

 */



GLOBAL void

jpeg_abort_compress (j_compress_ptr cinfo)

{

  jpeg_abort((j_common_ptr) cinfo); /* use common routine */

}





/*

 * Forcibly suppress or un-suppress all quantization and Huffman tables.

 * Marks all currently defined tables as already written (if suppress)

 * or not written (if !suppress).  This will control whether they get emitted

 * by a subsequent jpeg_start_compress call.

 *

 * This routine is exported for use by applications that want to produce

 * abbreviated JPEG datastreams.  It logically belongs in jcparam.c, but

 * since it is called by jpeg_start_compress, we put it here --- otherwise

 * jcparam.o would be linked whether the application used it or not.

 */



GLOBAL void

jpeg_suppress_tables (j_compress_ptr cinfo, boolean suppress)

{

  int i;

  JQUANT_TBL * qtbl;

  JHUFF_TBL * htbl;



  for (i = 0; i < NUM_QUANT_TBLS; i++) {

    if ((qtbl = cinfo->quant_tbl_ptrs[i]) != NULL)

      qtbl->sent_table = suppress;

  }



  for (i = 0; i < NUM_HUFF_TBLS; i++) {

    if ((htbl = cinfo->dc_huff_tbl_ptrs[i]) != NULL)

      htbl->sent_table = suppress;

    if ((htbl = cinfo->ac_huff_tbl_ptrs[i]) != NULL)

      htbl->sent_table = suppress;

  }

}





/*

 * Finish JPEG compression.

 *

 * If a multipass operating mode was selected, this may do a great deal of

 * work including most of the actual output.

 */



GLOBAL void

jpeg_finish_compress (j_compress_ptr cinfo)

{

  JDIMENSION iMCU_row;



  if (cinfo->global_state == CSTATE_SCANNING ||

      cinfo->global_state == CSTATE_RAW_OK) {

    /* Terminate first pass */

    if (cinfo->next_scanline < cinfo->image_height)

      ERREXIT(cinfo, JERR_TOO_LITTLE_DATA);

    (*cinfo->master->finish_pass) (cinfo);

  } else if (cinfo->global_state != CSTATE_WRCOEFS)

    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);

  /* Perform any remaining passes */

  while (! cinfo->master->is_last_pass) {

    (*cinfo->master->prepare_for_pass) (cinfo);

    for (iMCU_row = 0; iMCU_row < cinfo->total_iMCU_rows; iMCU_row++) {

      if (cinfo->progress != NULL) {

	cinfo->progress->pass_counter = (long) iMCU_row;

	cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows;

	(*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);

      }

      /* We bypass the main controller and invoke coef controller directly;

       * all work is being done from the coefficient buffer.

       */

      if (! (*cinfo->coef->compress_data) (cinfo, (JSAMPIMAGE) NULL))

	ERREXIT(cinfo, JERR_CANT_SUSPEND);

    }

    (*cinfo->master->finish_pass) (cinfo);

  }

  /* Write EOI, do final cleanup */

  (*cinfo->marker->write_file_trailer) (cinfo);

  (*cinfo->dest->term_destination) (cinfo);

  /* We can use jpeg_abort to release memory and reset global_state */

  jpeg_abort((j_common_ptr) cinfo);

}





/*

 * Write a special marker.

 * This is only recommended for writing COM or APPn markers.

 * Must be called after jpeg_start_compress() and before

 * first call to jpeg_write_scanlines() or jpeg_write_raw_data().

 */



GLOBAL void

jpeg_write_marker (j_compress_ptr cinfo, int marker,

		   const JOCTET *dataptr, unsigned int datalen)

{

  if (cinfo->next_scanline != 0 ||

      (cinfo->global_state != CSTATE_SCANNING &&

       cinfo->global_state != CSTATE_RAW_OK &&

       cinfo->global_state != CSTATE_WRCOEFS))

    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);



  (*cinfo->marker->write_any_marker) (cinfo, marker, dataptr, datalen);

}





/*

 * Alternate compression function: just write an abbreviated table file.

 * Before calling this, all parameters and a data destination must be set up.

 *

 * To produce a pair of files containing abbreviated tables and abbreviated

 * image data, one would proceed as follows:

 *

 *		initialize JPEG object

 *		set JPEG parameters

 *		set destination to table file

 *		jpeg_write_tables(cinfo);

 *		set destination to image file

 *		jpeg_start_compress(cinfo, FALSE);

 *		write data...

 *		jpeg_finish_compress(cinfo);

 *

 * jpeg_write_tables has the side effect of marking all tables written

 * (same as jpeg_suppress_tables(..., TRUE)).  Thus a subsequent start_compress

 * will not re-emit the tables unless it is passed write_all_tables=TRUE.

 */



GLOBAL void

jpeg_write_tables (j_compress_ptr cinfo)

{

  if (cinfo->global_state != CSTATE_START)

    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);



  /* (Re)initialize error mgr and destination modules */

  (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);

  (*cinfo->dest->init_destination) (cinfo);

  /* Initialize the marker writer ... bit of a crock to do it here. */

  jinit_marker_writer(cinfo);

  /* Write them tables! */

  (*cinfo->marker->write_tables_only) (cinfo);

  /* And clean up. */

  (*cinfo->dest->term_destination) (cinfo);

  /* We can use jpeg_abort to release memory. */

  jpeg_abort((j_common_ptr) cinfo);

}

